home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / ax_mbx < prev    next >
Text File  |  1994-03-03  |  36KB  |  863 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <ctype.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "ax25.h"
  9. #include "timer.h"
  10. #include "iface.h"
  11. #include "lapb.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "ax_mbx.h"
  15. #include "cmdparse.h"
  16. #include "smtp.h"
  17. #include "misc.h"
  18.  
  19. /*
  20. #define MBDEBUG
  21. */
  22.  
  23. struct mbx *mbox[NUMMBX] ;
  24. int ax25mbox ;
  25.  
  26. static char mbbanner[] =
  27.         "[NET-$]\rWelcome %s to the %s TCP/IP Personal Mailbox.\r(C)hat, (S)end, (B)ye >\r" ;
  28. static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
  29.  
  30. static void domboxdisplay(void);
  31. static struct mbx *newmbx(void);
  32. static void free_mbx(struct mbx *);
  33. static int mbx_line(struct mbx *);
  34. static int mbx_msg(struct mbx *, char *);
  35. static int mbx_to(struct mbx *);
  36. static int mbx_data(struct mbx *);
  37.  
  38. int dombox(int argc, char **argv)
  39. {
  40.         if (argc < 2) {
  41.                 domboxdisplay() ;
  42.                 return 0 ;
  43.         }
  44.  
  45.         if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  46.                 ax25mbox = 1 ;
  47.         else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  48.                 ax25mbox = 0 ;
  49.         else if (argv[1][0] == '?')
  50.                 cwprintf(NULL, "ax25 mailbox is %s\r\n", ax25mbox ? "on" : "off") ;
  51.         else
  52.                 cwprintf(NULL, "usage: mbox [y|n|?]\r\n") ;
  53.  
  54.         return 0 ;
  55. }
  56.  
  57. static void domboxdisplay(void)
  58. {
  59.         int i ;
  60.         struct mbx *m ;
  61.         static char *states[] = {"NONE","CMD","SUBJ","DATA"} ;
  62.         static char *mbtype[] = {"NONE","AX25 ","NET/ROM"} ;
  63.         
  64.         cwprintf(NULL, " User     State     Type      &cb     &mbx   BBS\r\n") ;
  65.  
  66.         for (i = 0 ; i < NUMMBX ; i++)
  67.                 if ((m = mbox[i]) != NULLMBX)
  68.                         cwprintf(NULL, "%-10s %-4s     %-7s   %04x    %04x   %s\r\n", m->name,
  69.                         states[m->state], mbtype[m->type],
  70.                         m->type == MBX_AX25 ? (int)m->cb.ax25_cb : (int)m->cb.nr4_cb,
  71.                         (int)m, m->mblforw ? "Yes" : " No") ;
  72. }
  73.  
  74.         
  75. static struct mbx *newmbx(void)
  76. {
  77.         int i ;
  78.         struct mbx *m ;
  79.  
  80.         for (i = 0 ; i < NUMMBX ; i++)
  81.                 if (mbox[i] == NULLMBX) {
  82.                         if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx))) == NULLMBX)
  83.                                 return NULLMBX ;
  84.                         m->mbnum = i ;
  85.                         return m ;
  86.                 }
  87.  
  88.         /* If we get here, there are no free mailbox sessions */
  89.  
  90.         return NULLMBX ;
  91. }
  92.  
  93.  
  94. /* Incoming mailbox session via ax.25 */
  95.  
  96. void mbx_incom(register struct ax25_cb *axp, int16 cnt)
  97. {
  98.         struct mbx *m ;
  99.         struct mbuf *bp;
  100.         char *cp ;
  101.         extern char hostname[] ;
  102.         
  103.         if ((m = newmbx()) == NULLMBX) {
  104.                 disc_ax25(axp) ;        /* no memory! */
  105.                 return ;
  106.         }
  107.  
  108.         m->state = MBX_CMD ;    /* start in command state */
  109.         m->type = MBX_AX25 ;    /* this is an ax.25 mailbox session */
  110.         m->cb.ax25_cb = axp ;
  111.  
  112.         pax25(m->name,&axp->addr.dest) ;
  113.         cp = strchr(m->name,'-') ;
  114.         if (cp != NULLCHAR)                     /* get rid of SSID */
  115.                 *cp = '\0' ;
  116.  
  117.         m->lp = m->line ;               /* point line pointer at buffer */
  118.         axp->r_upcall = (void(*)())mbx_rx ;
  119.         axp->s_upcall = mbx_state ;
  120.         axp->user = (char *)m ;
  121.  
  122.         /* The following is necessary because we didn't know we had a */
  123.         /* "real" ax25 connection until a data packet came in.  We    */
  124.         /* can't be spitting banners out at every station who connects, */
  125.         /* since they might be a net/rom or IP station.  Sorry.  */
  126.         
  127.         bp = recv_ax25(axp,cnt) ;               /* get the initial input */
  128.         free_p(bp) ;                                    /* and throw it away to avoid confusion */
  129.  
  130.         /* Now say hi */
  131.         
  132.         if ((bp = alloc_mbuf(strlen(hostname) + strlen(m->name)
  133.                         + strlen(mbbanner) + 2)) == NULLBUF) {
  134.                 disc_ax25(axp) ; /* mbx_state will fix stuff up */
  135.                 return ;
  136.         }
  137.  
  138.         *bp->data = PID_NO_L3 ;  /* pid */
  139.         sprintf(bp->data+1,mbbanner,m->name,hostname) ;
  140.         bp->cnt = strlen(bp->data+1) + 1 ;
  141.  
  142.         send_ax25(axp,bp) ;     /* send greeting message and menu */
  143.         log_event(NULL,"AX25 Mailbox session requested : %s",m->name);
  144.  
  145. }
  146.  
  147. /* receive upcall for ax.25 */
  148. /* mbx_rx collects lines, and calls mbx_line when they are complete. */
  149. /* If the lines get too long, it arbitrarily breaks them. */
  150.  
  151. void mbx_rx(struct ax25_cb *axp, int16 cnt)
  152. {
  153.         struct mbuf *bp;
  154.         struct mbx *m ;
  155.         char c ;
  156.         
  157.         m = (struct mbx *)axp->user ;
  158.         
  159.         if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
  160.                 return ;
  161.  
  162.         while (pullone(&bp,&c) == 1)
  163.         {
  164.                 if (c == '\r')
  165.                 {
  166.                         *m->lp = '\0' ;                 /* null terminate */
  167.                         if (mbx_line(m) == -1)
  168.                         {        /* call the line processor */
  169.                                 free_p(bp) ;            /* toss the rest */
  170.                                 break ;                         /* get out - we're obsolete */
  171.                         }
  172.                         m->lp = m->line ;               /* reset the pointer */
  173.                 }
  174.                 else if ((m->lp - m->line) == (MBXLINE - 1)) {
  175.                         *m->lp++ = c ;
  176.                         *m->lp = '\0' ;
  177.                         if (mbx_line(m) == -1) {
  178.                                 free_p(bp) ;
  179.                                 break ;
  180.                         }
  181.                         m->lp = m->line ;
  182.                 }
  183.                 else
  184.                         *m->lp++ = c ;
  185.         }
  186. }
  187.  
  188. /* state upcall for ax.25 */
  189.  
  190. void mbx_state(struct ax25_cb *axp, int old, int new)
  191. {
  192.         struct mbx *m ;
  193.                   
  194.         old = old;
  195.  
  196.         m = (struct mbx *)axp->user ;
  197.  
  198.         /* dummy for now ... */
  199.         if (new == DISCONNECTED && axp->user != NULLCHAR) {
  200.                 axp->user = NULLCHAR ;
  201.                 free_mbx(m) ;
  202.         }
  203. }
  204.  
  205.  
  206. /* Incoming mailbox session via net/rom */
  207.  
  208. void mbx_nr4incom(register struct nr4cb *cb)
  209. {
  210.         struct mbx *m ;
  211.         struct mbuf *bp ;
  212.         char *cp ;
  213.         extern char hostname[] ;
  214.         
  215.         if ((m = newmbx()) == NULLMBX) {
  216.                 disc_nr4(cb) ;  /* no memory! */
  217.                 return ;
  218.         }
  219.  
  220.         m->state = MBX_CMD ;    /* start in command state */
  221.         m->type = MBX_NETROM ;  /* mailbox session type is net/rom */
  222.         m->cb.nr4_cb = cb ;
  223.  
  224.         pax25(m->name,&cb->user) ;
  225.         cp = strchr(m->name,'-') ;
  226.         if (cp != NULLCHAR)                     /* get rid of SSID */
  227.                 *cp = '\0' ;
  228.  
  229.         m->lp = m->line ;               /* point line pointer at buffer */
  230.         cb->r_upcall = (void(*)())mbx_nr4rx ;
  231.         cb->s_upcall = mbx_nr4state ;
  232.         cb->puser = (char *)m ;
  233.  
  234.         /* Say hi */
  235.         
  236.         if ((bp = alloc_mbuf(strlen(hostname) + strlen(m->name)
  237.                         + strlen(mbbanner) + 1)) == NULLBUF) {
  238.                 disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
  239.                 return ;
  240.         }
  241.  
  242.         sprintf(bp->data,mbbanner,m->name,hostname) ;
  243.         bp->cnt = strlen(bp->data) ;
  244.  
  245.         send_nr4(cb,bp) ;           /* send greeting message and menu */
  246.         log_event(NULL,"NET/ROM Mailbox session requested : %s",m->name);
  247.  
  248. }
  249.  
  250. /* receive upcall for net/rom */
  251. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  252. /* If the lines get too long, it arbitrarily breaks them. */
  253.  
  254. void mbx_nr4rx(struct nr4cb *cb, int16 cnt)
  255. {
  256.         struct mbuf *bp ;
  257.         struct mbx *m ;
  258.         char c ;
  259.         
  260.         m = (struct mbx *)cb->puser ;
  261.         
  262.         if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
  263.                 return ;
  264.  
  265.         while (pullone(&bp,&c) == 1)
  266.         {
  267.                 if (c == '\r')
  268.                 {
  269.                         *m->lp = '\0' ;                 /* null terminate */
  270.                         if (mbx_line(m) == -1) {        /* call the line processor */
  271.                                 free_p(bp) ;            /* toss the rest */
  272.                                 break ;                 /* get out - we're obsolete */
  273.                         }
  274.                         m->lp = m->line ;               /* reset the pointer */
  275.                 }
  276.                 else if ((m->lp - m->line) == (MBXLINE - 1)) {
  277.                         *m->lp++ = c ;
  278.                         *m->lp = '\0' ;
  279.                         if (mbx_line(m) == -1) {
  280.                                 free_p(bp) ;
  281.                                 break ;
  282.                         }
  283.                         m->lp = m->line ;
  284.                 }
  285.                 else
  286.                         *m->lp++ = c ;
  287.         }
  288. }
  289.  
  290. /* state upcall for net/rom */
  291.  
  292. void mbx_nr4state(struct nr4cb *cb, int old, int new)
  293. {
  294.         struct mbx *m ;
  295.  
  296.         old = old;
  297.         
  298.         m = (struct mbx *)cb->puser ;
  299.  
  300.         if (new == NR4STDISC && cb->puser != NULLCHAR) {
  301.                 cb->puser = NULLCHAR ;
  302.                 free_mbx(m) ;
  303.         }
  304. }
  305.  
  306. static void free_mbx(struct mbx *m)
  307. {
  308.         if (m->to != NULLCHAR)
  309.                 free(m->to) ;
  310.  
  311.         if (m->tofrom != NULLCHAR)
  312.                 free(m->tofrom) ;
  313.  
  314.         if (m->tomsgid != NULLCHAR)
  315.                 free(m->tomsgid) ;
  316.                 
  317.         if (m->tfile != NULLFILE)
  318.                 fclose(m->tfile) ;
  319.  
  320.         mbox[m->mbnum] = NULLMBX ;
  321.         
  322.         free(m) ;
  323. }
  324.  
  325.  
  326. static int mbx_line(struct mbx *m)
  327. {
  328.         char *host ;
  329.         extern char hostname[] ;
  330.         extern int attended;
  331.         char fullfrom[80] ;
  332.         
  333.         if (m->state == MBX_CMD) {
  334.                 switch (tolower(m->line[0])) {
  335.                         case '*':       /* could be MBL/RLI *** Done */
  336.                                 if (!m->mblforw || strncmp(m->line,"*** Done",8))
  337.                                         {
  338.                                         mbx_msg(m,"Huh?\r") ;
  339.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  340.                                         break ;
  341.                                         }       /* drop thru if MBL and *** Done */
  342.                         case 'b':       /* bye - bye */
  343.                                 switch (m->type) {
  344.                                   case MBX_AX25:
  345.                                         m->cb.ax25_cb->user = NULLCHAR ;
  346.                                         disc_ax25(m->cb.ax25_cb) ;
  347.                                         break ;
  348.                                   case MBX_NETROM:
  349.                                         m->cb.nr4_cb->puser = NULLCHAR ;
  350.                                         disc_nr4(m->cb.nr4_cb) ;
  351.                                         break ;
  352.                                 }
  353.                                 free_mbx(m);
  354.                                 return -1 ;     /* tell line processor to quit */
  355.                                 break ;
  356.                         case 'c':       /* chat */
  357.                                 if(attended)
  358.                                         {
  359.                                         switch (m->type) {
  360.                                                 case MBX_AX25:
  361.                                                         m->cb.ax25_cb->user = NULLCHAR ;
  362.                                                         log_event(NULL,"AX25 Mailbox -> Chat requested : %s",m->name);
  363.                                                         ax_session(m->cb.ax25_cb,0) ;   /* make it a chat session */
  364.                                                         break ;
  365.                                                 case MBX_NETROM:
  366.                                                         m->cb.nr4_cb->puser = NULLCHAR ;
  367.                                                         log_event(NULL,"NET/ROM Mailbox -> Chat requested : %s",m->name);
  368.                                                         nr4_session(m->cb.nr4_cb) ;
  369.                                                         break ;
  370.                                                         }
  371.                                         free_mbx(m);
  372.                                         }
  373.                                 else    
  374.                                         {
  375.                                         mbx_msg(m,"Sorry..the system is UNATTENDED at the moment.\r") ;
  376.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  377.                                         break ;
  378.                                         }
  379.                                 return -1 ;
  380.                                 break ;
  381.                         case 's': {
  382.                                 int badsubj = 0 ;
  383.  
  384.                                 /* Get S-command type (B,P,T, etc.) */
  385.                                 
  386.                                 if (m->line[1] == '\0')
  387.                                         m->stype = ' ' ;
  388.                                 else
  389.                                         m->stype = toupper(m->line[1]) ;
  390.                                         
  391.                                 if (mbx_to(m) == -1) {
  392.                                         if (m->mblforw)
  393.                                                 mbx_msg(m,"NO\r") ;
  394.                                         else {
  395.                                                 mbx_msg(m,
  396.                                                         "S command syntax error - format is:\r") ;
  397.                                                 mbx_msg(m,
  398.                                                   "  S name [@ host] [< from_addr] [$bulletin_id]\r") ;
  399.                                         }
  400.                                         badsubj++ ;
  401.                                 }
  402.                                 else if (validate_address(m->to) == 0)   {
  403.                                         if (m->mblforw)
  404.                                                 mbx_msg(m, "NO\r") ;
  405.                                         else
  406.                                                 mbx_msg(m, "Bad user or host name\r") ;
  407.                                         free(m->to) ;
  408.                                         m->to = NULLCHAR ;
  409.                                         if (m->tofrom) {
  410.                                                 free(m->tofrom) ;
  411.                                                 m->tofrom = NULLCHAR ;
  412.                                         }
  413.                                         if (m->tomsgid) {
  414.                                                 free(m->tomsgid) ;
  415.                                                 m->tomsgid = NULLCHAR ;
  416.                                         }
  417.                                         badsubj++ ;
  418.                                 }
  419.  
  420.                                 if (badsubj)
  421.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  422.                                 else {
  423.                                         m->state = MBX_SUBJ ;
  424.                                         mbx_msg(m,      m->mblforw ? "OK\r" : "Subject:\r") ;
  425.                                 }
  426.                                 break ;
  427.                         }
  428.                         case '[':
  429.                                 if (m->line[strlen(m->line)-1] == ']')
  430.                                         {
  431.                                         m->mblforw = 1 ;
  432.                                         mbx_msg(m,">\r") ;
  433.                                         }
  434.                                 else
  435.                                         {
  436.                                         mbx_msg(m,"Huh?\r") ;
  437.                                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  438.                                         }
  439.                                 break ;
  440.                         case 'f':
  441.                                 if (m->line[1] == '>' && m->mblforw)
  442.                                         {
  443.                                         mbx_msg(m,"*** Done\r>\r") ;
  444.                                         break ;
  445.                                         }
  446.                                 /* Otherwise drop through to "huh?" */
  447.                         default:
  448.                                 mbx_msg(m,"Huh?\r") ;
  449.                                 mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  450.                 }
  451.         return 0 ;
  452.         }
  453.         else if (m->state == MBX_SUBJ) {
  454.                 if (mbx_data(m) == -1) {
  455.                         mbx_msg(m,"Can't create temp file for mail\r") ;
  456.                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  457.                         free(m->to) ;
  458.                         m->to = NULLCHAR ;
  459.                         if (m->tofrom) {
  460.                                 free(m->tofrom) ;
  461.                                 m->tofrom = NULLCHAR ;
  462.                         }
  463.                         if (m->tomsgid) {
  464.                                 free(m->tomsgid) ;
  465.                                 m->tomsgid = NULLCHAR ;
  466.                         }
  467.                         m->state = MBX_CMD ;
  468.                         return 0 ;
  469.                 }
  470.                 m->state = MBX_DATA ;
  471.                 if (m->mblforw == 0)
  472.                         mbx_msg(m,
  473.                           "Enter message.  Terminate with /EX or ^Z in first column:\r") ;
  474.                 return 0 ;
  475.         }
  476.         else if (m->state == MBX_DATA) {
  477.                 if (m->line[0] == 0x1a ||
  478.                         strcmp(m->line, "/ex") == 0 ||
  479.                         strcmp(m->line, "/EX") == 0) {
  480.                         if ((host = strchr(m->to,'@')) == NULLCHAR)
  481.                                 host = hostname ;               /* use our hostname */
  482.                         else
  483.                                 host++ ;                                /* use the host part of address */
  484.  
  485.                         /* make up full from name for work file */
  486.                         sprintf(fullfrom,"%s@%s",m->name,hostname) ;
  487.                         
  488.                         fseek(m->tfile,0L,0) ;          /* reset to beginning */
  489.                         if (queuejob((void *)0,m->tfile,host,m->to,fullfrom) != 0)
  490.                                 mbx_msg(m,"Couldn't queue message for delivery\r") ;
  491.  
  492.                         free(m->to) ;
  493.                         m->to = NULLCHAR ;
  494.                         if (m->tofrom) {
  495.                                 free(m->tofrom) ;
  496.                                 m->tofrom = NULLCHAR ;
  497.                         }
  498.                         if (m->tomsgid) {
  499.                                 free(m->tomsgid) ;
  500.                                 m->tomsgid = NULLCHAR ;
  501.                         }
  502.                         fclose(m->tfile) ;
  503.                         m->tfile = NULLFILE ;
  504.                         m->state = MBX_CMD ;
  505.                         smtptick();
  506.                         mbx_msg(m, m->mblforw ? ">\r" : mbmenu) ;
  507.                         return 0 ;
  508.                 }
  509.                 /* not done yet! */
  510.                 fprintf(m->tfile,"%s\r\n",m->line) ;
  511.                 return 0 ;
  512.         }
  513.  
  514.         return 0;  /* JSN Not sure */
  515. }
  516.  
  517. static int mbx_msg(struct mbx *m, char *msg)
  518. {
  519.         int len ;
  520.         struct mbuf *bp ;
  521.         struct ax25_cb *axp ;
  522.         struct nr4cb *cb ;
  523.  
  524.         len = strlen(msg) ;
  525.  
  526.         switch (m->type) {
  527.           case MBX_AX25:
  528.             axp = m->cb.ax25_cb ;
  529.                         
  530.                 if ((bp = alloc_mbuf(len+1)) == NULLBUF) {
  531.                         disc_ax25(axp) ;
  532.                         return -1 ;
  533.                 }
  534.  
  535.                 bp->cnt = len + 1 ;
  536.         
  537.                 *bp->data = PID_NO_L3 ;
  538.         
  539.                 memcpy(bp->data+1, msg, len) ;
  540.  
  541.                 send_ax25(axp,bp) ;
  542.  
  543.                 break ;
  544.  
  545.           case MBX_NETROM:
  546.             cb = m->cb.nr4_cb ;
  547.  
  548.                 if ((bp = alloc_mbuf(len)) == NULLBUF) {
  549.                         disc_nr4(cb) ;
  550.                         return -1 ;
  551.                 }
  552.  
  553.                 bp->cnt = len ;
  554.  
  555.                 memcpy(bp->data, msg, len) ;
  556.  
  557.                 send_nr4(cb, bp) ;
  558.  
  559.                 break ;
  560.         }
  561.         return 0 ;
  562. }
  563.  
  564.  
  565. /* States for send line parser state machine */
  566.  
  567. #define         SKIP_CMD                1
  568. #define         LOOK_FOR_USER           2
  569. #define         IN_USER                 3
  570. #define         AFTER_USER              4
  571. #define         LOOK_FOR_HOST           5
  572. #define         IN_HOST                 6
  573. #define         AFTER_HOST              7
  574. #define         LOOK_FOR_FROM           8
  575. #define         IN_FROM                 9
  576. #define         AFTER_FROM              10
  577. #define         LOOK_FOR_MSGID          11
  578. #define         IN_MSGID                12
  579. #define         FINAL_STATE             13
  580. #define         ERROR_STATE             14
  581.  
  582. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  583.  * return 0
  584.  */
  585. static int mbx_to(struct mbx *m)
  586. {
  587.         register char *cp;
  588.         int state ;
  589.         char *user, *host, *from, *msgid ;
  590.         int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
  591.         
  592.         cp = m->line ;
  593.  
  594.         for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
  595. #ifdef MBDEBUG
  596.                 cwprintf(NULL, "State is %d, char is %c\r\n", state, *cp) ;
  597. #endif
  598.                 switch (state) {
  599.                         case SKIP_CMD:
  600.                                 if (*cp == '\0')
  601.                                         state = ERROR_STATE ;           /* no user */
  602.                                 else if (isspace(*cp))
  603.                                         state = LOOK_FOR_USER ;
  604.                                 break ;
  605.                         case LOOK_FOR_USER:
  606.                                 if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
  607.                                         state = ERROR_STATE ;           /* no user */
  608.                                 else if (!isspace(*cp)) {               /* found start of user */
  609.                                         user = cp ;                                     /* point at start */
  610.                                         userlen++ ;                                     /* start counting */
  611.                                         state = IN_USER ;
  612.                                 }
  613.                                 break ;
  614.                         case IN_USER:
  615.                                 switch (*cp) {
  616.                                         case '\0':                                      /* found username only */
  617.                                                 state = FINAL_STATE ;
  618.                                                 break ;
  619.                                         case '@':
  620.                                                 state = LOOK_FOR_HOST ; /* hostname should follow */
  621.                                                 break ;
  622.                                         case '<':
  623.                                                 state = LOOK_FOR_FROM ; /* from name should follow */
  624.                                                 break ;
  625.                                         case '$':
  626.                                                 state = LOOK_FOR_MSGID ; /* message id should follow */
  627.                                                 break ;
  628.                                         default:
  629.                                                 if (isspace(*cp))
  630.                                                         state = AFTER_USER ;    /* white space */
  631.                                                 else
  632.                                                         userlen++ ;                             /* part of username */
  633.                                 }
  634.                                 break ;
  635.                         case AFTER_USER:
  636.                                 switch (*cp) {
  637.                                         case '\0':
  638.                                                 state = FINAL_STATE ;           /* found username only */
  639.                                                 break ;
  640.                                         case '@':
  641.                                                 state = LOOK_FOR_HOST ;         /* hostname follows */
  642.                                                 break ;
  643.                                         case '<':
  644.                                                 state = LOOK_FOR_FROM ;         /* fromname follows */
  645.                                                 break ;
  646.                                         case '$':
  647.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  648.                                                 break ;
  649.                                         default:
  650.                                                 if (!isspace(*cp))
  651.                                                         state = ERROR_STATE ;
  652.                                 }
  653.                                 break ;
  654.                         case LOOK_FOR_HOST:
  655.                                 switch (*cp) {
  656.                                         case '\0':                                      /* user@? */
  657.                                         case '@':                                       /* user@@ */
  658.                                         case '<':                                       /* user@< */
  659.                                         case '$':                                       /* user@$ */
  660.                                                 state = ERROR_STATE ;
  661.                                                 break ;
  662.                                         default:
  663.                                                 if (!isspace(*cp)) {
  664.                                                         host = cp ;
  665.                                                         hostlen++ ;
  666.                                                         state = IN_HOST ;
  667.                                                 }
  668.                                 }
  669.                                 break ;
  670.                         case IN_HOST:
  671.                                 switch (*cp) {
  672.                                         case '\0':
  673.                                                 state = FINAL_STATE ;           /* found user@host */
  674.                                                 break ;
  675.                                         case '@':
  676.                                                 state = ERROR_STATE ;           /* user@host@? */
  677.                                                 break ;
  678.                                         case '<':
  679.                                                 state = LOOK_FOR_FROM ;         /* fromname follows */
  680.                                                 break ;
  681.                                         case '$':
  682.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  683.                                                 break ;
  684.                                         default:
  685.                                                 if (isspace(*cp))
  686.                                                         state = AFTER_HOST ;
  687.                                                 else
  688.                                                         hostlen++ ;
  689.                                 }
  690.                                 break ;
  691.                         case AFTER_HOST:
  692.                                 switch (*cp) {
  693.                                         case '\0':
  694.                                                 state = FINAL_STATE ;           /* user@host */
  695.                                                 break ;
  696.                                         case '@':
  697.                                                 state = ERROR_STATE ;           /* user@host @ */
  698.                                                 break ;
  699.                                         case '<':
  700.                                                 state = LOOK_FOR_FROM ;         /* user@host < */
  701.                                                 break ;
  702.                                         case '$':
  703.                                                 state = LOOK_FOR_MSGID ;        /* user@host $ */
  704.                                                 break ;
  705.                                         default:
  706.                                                 if (!isspace(*cp))
  707.                                                         state = ERROR_STATE ;   /* user@host foo */
  708.                                 }
  709.                                 break ;
  710.                         case LOOK_FOR_FROM:
  711.                                 switch (*cp) {
  712.                                         case '\0':                                      /* user@host <? */
  713.                                         case '@':                                       /* user@host <@ */
  714.                                         case '<':                                       /* user@host << */
  715.                                         case '$':                                       /* user@host <$ */
  716.                                                 state = ERROR_STATE ;
  717.                                                 break ;
  718.                                         default:
  719.                                                 if (!isspace(*cp)) {
  720.                                                         from = cp ;
  721.                                                         fromlen++ ;
  722.                                                         state = IN_FROM ;
  723.                                                 }
  724.                                 }
  725.                                 break ;
  726.                         case IN_FROM:
  727.                                 switch (*cp) {
  728.                                         case '\0':
  729.                                                 state = FINAL_STATE ;           /* user@host <foo */
  730.                                                 break ;
  731.                                         case '<':
  732.                                                 state = ERROR_STATE ;           /* user@host <foo< */
  733.                                                 break ;
  734.                                         case '$':
  735.                                                 state = LOOK_FOR_MSGID ;        /* message id follows */
  736.                                                 break ;
  737.                                         default:
  738.                                                 if (isspace(*cp))
  739.                                                         state = AFTER_FROM ;
  740.                                                 else
  741.                                                         fromlen++ ;
  742.                                 }
  743.                                 break ;
  744.                         case AFTER_FROM:
  745.                                 switch (*cp) {
  746.                                         case '\0':
  747.                                                 state = FINAL_STATE ;           /* user@host <foo */
  748.                                                 break ;
  749.                                         case '@':                                               /* user@host <foo @ */
  750.                                         case '<':                                               /* user@host <foo < */
  751.                                                 state = ERROR_STATE ;
  752.                                                 break ;
  753.                                         case '$':
  754.                                                 state = LOOK_FOR_MSGID ;        /* user@host <foo $ */
  755.                                                 break ;
  756.                                         default:
  757.                                                 if (!isspace(*cp))
  758.                                                         state = ERROR_STATE ;   /* user@host foo */
  759.                                 }
  760.                                 break ;
  761.                         case LOOK_FOR_MSGID:
  762.                                 if (*cp == '\0')
  763.                                         state = ERROR_STATE ;                   /* msgid = $? */
  764.                                 else if (isspace(*cp))
  765.                                         state = ERROR_STATE ;                   /* user@host <foo $ bar */
  766.                                 else {
  767.                                         msgid = cp ;
  768.                                         msgidlen++ ;
  769.                                         state = IN_MSGID ;
  770.                                 }
  771.                                 break ;
  772.                         case IN_MSGID:
  773.                                 if (*cp == '\0')
  774.                                         state = FINAL_STATE ;
  775.                                 else if (isspace(*cp))
  776.                                         state = FINAL_STATE ;
  777.                                 else
  778.                                         msgidlen++ ;
  779.                                 break ;
  780.                         default:
  781.                                 /* what are we doing in this state? */
  782.                                 state = ERROR_STATE ;
  783.                 }
  784.         }
  785.  
  786.         if (state == ERROR_STATE)
  787.                 return -1 ;             /* syntax error */
  788.  
  789.         if ((m->to = malloc(userlen + hostlen + 2)) == NULLCHAR)
  790.                 return -1 ;             /* no room for to address */
  791.  
  792.         strncpy(m->to, user, userlen) ;
  793.         m->to[userlen] = '\0' ;
  794.         
  795.         if (hostlen) {
  796.                 m->to[userlen] = '@' ;
  797.                 strncpy(m->to + userlen + 1, host, hostlen) ;
  798.                 m->to[userlen + hostlen + 1] = '\0' ;
  799.         }
  800.  
  801.         if (fromlen) {
  802.                 if ((m->tofrom = malloc(fromlen + 1)) == NULLCHAR) {
  803.                         free(m->to) ;
  804.                         m->to = NULLCHAR ;
  805.                         return -1 ;
  806.                 }
  807.                 strncpy(m->tofrom, from, fromlen) ;
  808.                 m->tofrom[fromlen] = '\0' ;
  809.         }
  810.  
  811.         if (msgidlen) {
  812.                 if ((m->tomsgid = malloc(msgidlen + 1)) == NULLCHAR) {
  813.                         free(m->to) ;
  814.                         m->to = NULLCHAR ;
  815.                         if (fromlen) {
  816.                                 free(m->tofrom) ;
  817.                                 m->tofrom = NULLCHAR ;
  818.                         }
  819.                         return -1 ;
  820.                 }
  821.                 strncpy(m->tomsgid, msgid, msgidlen) ;
  822.                 m->tomsgid[msgidlen] = '\0' ;
  823.         }
  824.         
  825.         return 0 ;
  826. }
  827.  
  828. /* This opens the data file and writes the mail header into it.
  829.  * Returns 0 if OK, and -1 if not.
  830.  */
  831.  
  832. static int mbx_data(struct mbx *m)
  833. {
  834.         time_t t;
  835.         extern char hostname[] ;
  836.         
  837.         if ((m->tfile = tmpfile()) == NULLFILE)
  838.                 return -1 ;
  839.  
  840.         time(&t) ;
  841.         fprintf(m->tfile,"Date: %s",ptime(&t)) ;
  842.  
  843.         if (m->tomsgid)
  844.                 fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
  845.         else
  846.                 fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
  847.  
  848.         fprintf(m->tfile,"From: %s%%%s.BBS@%s\n",m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
  849.  
  850.         fprintf(m->tfile,"Reply-To: %s@%s\n",m->tofrom ? m->tofrom : m->name, m->name) ;
  851.  
  852.         fprintf(m->tfile,"To: %s\n",m->to) ;
  853.  
  854.         fprintf(m->tfile,"Subject: %s\n\n",m->line) ;
  855.  
  856.         if (m->stype != ' ')
  857.                 fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
  858.  
  859.         fprintf(m->tfile,"\n") ;
  860.  
  861.         return 0 ;
  862. }
  863.